<?php 
namespace app\task\controller;
use app\BaseController;
use think\facade\Db;
use app\common\lib\WxTemplateMsg;
class ArticlePlan extends BaseController
{
    //每天0时清空任务
    public function clear_sent_today(){
        // 获取当前时间的小时和分钟
        $hour = date('H'); // 获取小时，范围 00 到 23
        $minute = date('i'); // 获取分钟，范围 00 到 59

        // 判断当前时间是否大于 0 时 2 分
        if ($hour > '00' || ($hour == '00' && $minute > '02')) {
            // 如果当前时间大于 0 时 2 分，禁止执行程序
            echo "当前时间大于 0 时 2 分，禁止执行清空sent_today程序";exit;
        }
        //
        Db::execute("UPDATE db_push_plan SET sent_today = 0");
        echo "执行成功";exit;//一定要加上exit，否则debug开启后，宝塔日志里会记录相关调试代码
    }
    //针对站点不正确的计划暂停
    public function pause_plan(){
        $pushPlans = \app\common\model\PushPlan::where('is_open', 1)
            ->where('number_of_articles', '>', 0)
            ->select();
        foreach($pushPlans as $v){
            $site=\app\common\model\Site::find($v->site_id);
            if(!$site){
                \app\common\model\PushPlan::update(["id"=>$v->id,"is_open"=>0]);
            }
        }
    }
    //执行发送任务
    public function index()
    {
        // 获取当前时间（小时和分钟）格式为 "H:i"
        $currentTime = date('H:i');

        // 获取当前星期几（1到7，其中1代表星期一，7代表星期日）
        $currentDayOfWeek = date('N');

        // 获取当前日期（1到31）
        $currentDayOfMonth = date('j');

        // 获取所有当前开启的推送计划
        $pushPlans = \app\common\model\PushPlan::where('is_open', 1)
            ->where('number_of_articles', '>', 0)
            //->where('member_id', '=', 4)//==============================================正式使用后这里需要删除
            //->where("id","=","339")//用来测试具体哪个任务的
            ->where('sent_today', '<', Db::raw('number_of_articles'))
            //->limit(30)//这里不能加limit，因为有的发布计划对应的文章分类为0，sent_today一直也就是0如果限制条数的话超过条数的就无法发送了
            ->select();
        if(!count($pushPlans)){
            echo "没有要执行的任务了";
        }
        // 遍历每个推送计划，检查是否需要执行
        foreach ($pushPlans as $plan) {
            //根据$plan里的time_gap计算间隔时间
            if($plan->time_gap){
                $time_gap_arr=explode("-",$plan->time_gap);
                $start_time_gap=(int)$time_gap_arr[0];
                if(isset($time_gap_arr[1])){
                    $end_time_gap=(int)$time_gap_arr[1];
                    $time=time()-(rand($start_time_gap,$end_time_gap)*60);
                    $time=$time+rand(-5,5);//把秒数也打乱
                }else{
                    $time=time()-$start_time_gap*60;
                }
                //判断今天有没有发过数据，如果没有发过则说明是今天第一条发的，要在开始时间后+随机时间再发送，否则每天的第一条信息都是一样的
                if(\app\common\model\PushLog::where([
                    ["push_plan_id","=",$plan->id],
                    ["create_time",">=",strtotime('today')],
                ])->count()==0){
                    //虚拟一个发送时间（开始日期+小时+分）
                    $virtual=date("Y-m-d ".$plan->hour.":".$plan->minute.":00");
                    if(strtotime($virtual)>$time){
                        continue;
                    }
                }
                //查询最近一条时间有没有大于间隔时间
                else if(\app\common\model\PushLog::where([
                    ["push_plan_id","=",$plan->id],
                    ["create_time",">",$time],
                ])->count()){
                    continue;
                }
            }
            //
            // 根据频率和其他条件检查计划是否到期
            if ($this->isPlanDue($plan, $currentTime, $currentDayOfWeek, $currentDayOfMonth)) {
                //查询该分类下的文章总数
                $count=Db::name("article")
                    ->field("id")
                    ->where('state', '=', 2)
                    ->where('member_id', '=', $plan->member_id)
                    ->where('article_class_id', '=', $plan->article_class_id)
                    ->count();
                if(!$count){
                    echo "没有执行，plan_id".$plan->id."没有文章了<br>";
                    //没有文章了，这里可以执行相关的通知，但是要注意这个任务是每分钟运行的，不能每分钟都发消息
                    continue;
                }else{
                    //根据栏目随机查询文章
                    $articleAll=Db::name("article")
                        ->field("id")
                        ->where('state', '=', 2)
                        ->where('member_id', '=', $plan->member_id)
                        ->where('article_class_id', '=', $plan->article_class_id)
                        ->order("id asc")
                        ->limit(rand(0,$count-1),1)->select();
                    $article=$articleAll[0];
                    // 执行计划并将数据发送到用户接口（在这里调用你的发送接口）
                    $result = $this->executePlan($plan,$article['id']);
                    // 更新 "sent_today" 计数
                    \app\common\model\PushPlan::where('id', $plan->id)->inc('sent_today')->update();
                    //判断今日发送量（sent_today）是否==设定的数量（number_of_articles）
                    if($plan->number_of_articles==($plan->sent_today+1)){
                        $countSuccess=Db::name("push_log")->where([
                            ["push_plan_id","=",$plan->id],
                            ["state","=",1],
                            ["create_time","between",[strtotime(date('Y-m-d').' 00:00:00'),strtotime(date('Y-m-d').' 23:59:59')]],
                            ])->count();
                            //发送模板消息
                            WxTemplateMsg::send($plan->member_id,1, [
                                'thing3' => $plan->name,
                                'number13' => $plan->number_of_articles,
                                'time5' => date("Y-m-d H:i:s"),
                                'phrase15' => "计划完成",
                            ]);
                    }
                    //
                    echo "执行成功plan_id".$plan->id."<br>";
                }

            }else{
                echo "没有要触发的任务<br>";
            }
        }
        exit;
    }

    private function isPlanDue($plan, $currentTime, $currentDayOfWeek, $currentDayOfMonth)
    {
        switch ($plan->period) {
            case 1: // 每天
                return $this->checkHourAndMinute($plan->hour, $plan->minute, $currentTime);
            case 2: // 每周
                return in_array($currentDayOfWeek, explode(',', $plan->week))
                    && $this->checkHourAndMinute($plan->hour, $plan->minute, $currentTime);
            case 3: // 每月
                return $currentDayOfMonth == $plan->day
                    && $this->checkHourAndMinute($plan->hour, $plan->minute, $currentTime);
            default:
                return false; // 无效的频率
        }
    }

    
    private function checkHourAndMinute($hour, $minute, $currentTime)
    {
        list($currentHour, $currentMinute) = explode(':', $currentTime);
        return ($currentHour > $hour) || ($currentHour == $hour && $currentMinute >= $minute);
    }

    //执行发文章
    public function executePlan($plan,$article_id){
        echo "plan id:".$plan->id."<br>";
        $s=new \app\api\service\ArticlePushService([
            "article_id"=>$article_id,//要发布的文章id
            "site_id"=>$plan->site_id,//目标站点id
            "site_cat_id"=>$plan->site_cat_id,//目标站点的栏目id
            "insert_picture_class"=>$plan->is_insert_picture?$plan->img_class_id:0,//文章要调用的图片分类id
            "insert_picture_line"=>$plan->img_line,//图片插入段落的位置：0为随机，1为第一段前，n为第n段前，当n大于段落数则会插入到文章末尾（建议要放到最后一行可以设置为100）
            "relation_article_num"=>$plan->is_relation?json_decode($plan->relation_num,true):0,//查询关联的文章数量
            "relation_article_str"=>$plan->relation_title//在文章中插入相关文章的标题，默认为：相关文章
        ]);
        $s->getArticle();//查询文章
        $s->getSite();//查询站点
        $s->getSiteLink();//查询站点锚链接
        $s->repArticleKeywords();//替换文章中的关键词为站点里的词库
        $s->repSiteLink();//替换文章中的关键词锚链接
        //文章中插入图片
        if($s->insert_picture_class){
            $s->insertArticlePicture();
        }

        //文章内容增加相关文章
        if($s->relation_article_num){
            $s->setRelationArticle();
        }

        //获取发送的数据参数，返回值为array[data,cookies,headers,url,flag]
        $pushParam=$s->getPushFormData();
        //开始发送
        $result=$s->push($pushParam);
        if($result['status']){
            //发布成功
            $s->updateArticle($s::successState, $result['article_url']);//更新文章状态
            $s->addPushLog(1,'',$plan['id']);//增加发布日志
        }else{
            //发布失败
            $s->updateArticle($s::errorState);//更新文章状态
            $s->addPushLog(0,$result['msg'],$plan['id']);//增加发布日志
        }
        return true;
    }


}
